package com.gitee.wsl.scheduler.job.runtime.scheduler

import com.gitee.wsl.concurrent.api.SuspendRunnable
import com.gitee.wsl.concurrent.service.ScheduledExecutorService
import com.gitee.wsl.logger.Logger
import com.gitee.wsl.logger.debug
import com.gitee.wsl.logger.error
import com.gitee.wsl.logger.getLogger
import com.gitee.wsl.platform.concurrent.runBlocking
import kotlin.time.DurationUnit


abstract class SimplePeriodScheduler(
    private val executorService: ScheduledExecutorService,
    private val periodInMilliSeconds: Long
) {
    private val logger = Logger.getLogger<SimplePeriodScheduler>()

    protected fun run(block: SuspendRunnable) = run(block, 0)

    private fun run(block: SuspendRunnable, initialDelay: Long): Unit {
        if (executorService.isShutdown || executorService.isTerminated) {
            throw IllegalStateException("Scheduler has already been shutdown.")
        }
        executorService.scheduleAtFixedRate(initialDelay, periodInMilliSeconds, DurationUnit.MILLISECONDS){
            runBlocking {
                try {
                    block()
                } catch (e: Exception) {
                    logger.error("Scheduled task failed", e)
                    run(block, periodInMilliSeconds)
                    throw e
                }
            }
        }
    }

    open fun shutdown(): Unit {
        logger.debug("Shutting down ${this::class.simpleName}")
        executorService.shutdown()
    }
}